﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BReusable.StaticReflection;

namespace BReusable.Tests.StaticReflection
{
    [TestClass]
    public class MaybeTests
    {

        [TestMethod]
        public void MaybeShallowNullable_value_returnsValue()
        {
            //arrange
            var instance = new MaybeTestHelper();
            var expected = MaybeTestHelper.HasValueConstant;

            var actual = instance.MaybeShallowNullable(x => x.InstanceNullableIntFieldWithValue);

            Assert.AreEqual(expected, actual.Value);
        }

        [TestMethod]
        public void MaybeShallow_null_returnsNull()
        {
            var instance = new StaticReflection.MaybeTestHelper();
            instance.DeepProperty = null;

            var actual = instance.MaybeShallow(i => i.DeepProperty);
            Assert.IsNull(actual);
        }

        [TestMethod]
        public void MaybeDeep_PrimitiveValue_ThrowsArgumentException()
        {
            var instance = new MaybeTestHelper();
            try
            {
                var action = instance.MaybeDeep(x => x.InstanceIntField);
                Assert.Fail("Did not throw exception");
            }
            catch (Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(ArgumentException));
            }

        }

        [TestMethod]
        public void MaybeDeep_NestedValue_returnsValue()
        {
            var expected = "expected";
            var instance = new MaybeTestHelper()
                               {NestedInstance = new MaybeTestHelper() {DeepProperty =expected }};
            var actual = instance.MaybeDeep(x => x.NestedInstance.DeepProperty);

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void MaybeDeep_nullSource_returnsNull()
        {

            MaybeTestHelper instance = null;
            var actual = instance.MaybeDeep(x => x.NestedInstance.DeepProperty);

            Assert.IsNull(actual);

        }

        [TestMethod]
        public void MaybeDeep_nullFirstStep_returnsNull()
        {

            var instance = new MaybeTestHelper() {NestedInstance = null};
            var actual = instance.MaybeDeep(x => x.NestedInstance.DeepProperty);

            Assert.IsNull( actual);

        }

        [TestMethod]
        public void MaybeDeep_nullSecondStep_returnsNull()
        {
            var instance = new MaybeTestHelper()
                               {NestedInstance = new MaybeTestHelper() {NestedInstance = null}};
            var actual = instance.MaybeDeep(i => i.NestedInstance.NestedInstance.DeepProperty);
        }

        [TestMethod]
        public void Maybe_NullableValueWithNull_ReturnsNull()
        {
            var instance = new MaybeTestHelper();
            var actual = instance.MaybeDeep(x => x.InstanceNullableIntField);
            Assert.IsNull(actual);
        }

        [TestMethod]
        public void Maybe_NullableValueWithValue_ReturnsValue()
        {
            var instance = new MaybeTestHelper();
            int? expected = MaybeTestHelper.HasValueConstant;
            var actual = instance.MaybeDeep(x => x.InstanceNullableIntFieldWithValue);
            Assert.AreEqual(expected, actual);
        }

    }
}
